package com.ruoyi.tcp.tcpserver;


import com.alibaba.fastjson.JSONObject;

import com.ruoyi.lightkillPest.domain.device.SCDDeviceBatteryInfo;
import com.ruoyi.lightkillPest.domain.device.SCDDeviceDao;
import com.ruoyi.lightkillPest.mapper.SCDDeviceMapper;
import com.ruoyi.permission.Dao.SerDevicePermi;
import com.ruoyi.permission.domain.DevicePermiInfo;
import com.ruoyi.permission.mapper.SerDevicePermiMapper;
import com.ruoyi.tcp.domain.ChannelMap;
import com.ruoyi.utils.LocationUtil;
import com.ruoyi.xag.domain.IotDeviceInfo;
import com.ruoyi.xag.domain.datapoints.Weather;
import com.ruoyi.xag.domain.datapoints.WeatherSenorDataPoints;
import com.ruoyi.xag.domain.iotdevice.Location;
import com.ruoyi.xag.mapper.DeviceMapper;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hpsf.Decimal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.lang.Math.max;
import static java.lang.Math.min;

/**
 * @author hanyiming
 * @create 2021/9/9 10:12
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class TCPServerHandler extends ChannelInboundHandlerAdapter {

    @Autowired
    private SCDDeviceMapper scdDeviceMapper;

    @Autowired
    private SerDevicePermiMapper devicePermiMapper;

    @Autowired
    private DeviceMapper iotDeviceMapper;

    public ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);


    /**
     * 客户端连接会触发
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("连接成功...");
    }

    /**
     * 客户端发消息会触发
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        try {
            log.info("终端IP：" + ctx.channel().remoteAddress());
            log.info("收到数据：" + byteBuf.toString(CharsetUtil.UTF_8));
            String data = byteBuf.toString(CharsetUtil.UTF_8);
            //保存当前连接
            log.info("name：" + ctx.name());
            String channelName = ctx.channel().remoteAddress().toString();
            ChannelMap.addChannel(channelName,ctx.channel());
            String result = data.substring(6);
//            log.info("进行解析的数据：" + result);
            int cpIndex = result.indexOf("CP=");
            String cpValue = result.substring(cpIndex + 3, result.indexOf(";", cpIndex));
            String[] splitStrings = result.split("CP=" + cpValue);
            String result1 = splitStrings[0];
            String result2 ="CP=" + cpValue + splitStrings[1];
//            log.info("result1= " + result1);
//            log.info("result2= " + result2);
            String[] beforeFields = result1.split(";");
            Map<String,String> beforeMap = new HashMap<>();
            Map<String,String> afterMap = new HashMap<>();
            for(String field :beforeFields){
                String[] keyValue = field.split("=");
                beforeMap.put(keyValue[0],keyValue[1]);
            }
            Pattern pattern = Pattern.compile("CP=&&(.+?)&&");
            Matcher matcher = pattern.matcher(result2);
            if(matcher.find()){
                String cpData = matcher.group(1);
                String[] keyValuePairs = cpData.split(";");
                for(String keyValuePair : keyValuePairs){
                    String[] parts = keyValuePair.split("=");
                    if(parts.length ==2){
                        afterMap.put(parts[0],parts[1]);
                    }
                }
            }
            //判断是否属于气象土壤设备，默认不是
            int iotFlag = 0;
//            数据处理
            String deviceId = beforeMap.get("DevId");
            String deviceType = beforeMap.get("DevCls");
            String QN_date = beforeMap.get("QN");

            String dateTime = afterMap.get("DateTime");
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            Date date = dateFormat.parse(dateTime);
            double sunVoltRtd = Double.parseDouble(afterMap.get("SunVolt-Rtd"));
            double cellVoltRtd = Double.parseDouble(afterMap.get("CellVolt-Rtd"));
            double tempRtd = Double.parseDouble(afterMap.get("Temp-Rtd"));
            String latitude = afterMap.get("Dim-Rtd");
            String longitude = afterMap.get("Long-Rtd");
            double longitude_final = 0;
            double latitude_final = 0;
            double formattedLongitude = 0;
            double formattedLatitude = 0;
            if(!latitude.equals("-1") || !longitude.equals("-1")) {
//            <!--用于转换经纬度的格式-->
//            经度的度
                double ddd = Double.parseDouble(longitude.substring(0, 3));
//            经度的分
                double lo_mmmmmm = Double.parseDouble(longitude.substring(3, 9));
                double lo_decimal = lo_mmmmmm / 60.0;
                longitude_final = ddd + lo_decimal;

                double dd = Double.parseDouble(latitude.substring(0, 2));
                double la_mmmmmm = Double.parseDouble(latitude.substring(2, 8));
                double la_decimal = la_mmmmmm / 60.0;
                latitude_final = dd + la_decimal;

                // 创建DecimalFormat对象，指定保留小数点后五位
                DecimalFormat decimalFormat = new DecimalFormat("#.#####");
                // 格式化经度和纬度
                formattedLongitude = Double.valueOf(decimalFormat.format(longitude_final));
                formattedLatitude = Double.valueOf(decimalFormat.format(latitude_final));

//                scdDeviceDao.setLatitude(formattedLatitude);
//                scdDeviceDao.setLongitude(formattedLongitude);
            }
//            工作电压范围是（12.3-14.89）
            Double battery =( cellVoltRtd - 12.3 )/ 2.59 * 100.0;
            battery = min(max(battery, 0.0), 100.0);
//            工作模式
            String workMode = afterMap.get("Mode-Rtd");
            //            获取设置的工作模式和时控模式的工作开始时间
            Integer work_mode = null;
            String beginTime = null;
//            用于更新杀虫灯的表
            if(deviceType.equals("0001")) {
                SCDDeviceDao scdDeviceDao = new SCDDeviceDao();
                scdDeviceDao.setMessage(data);
                int fanStatus = Integer.parseInt((afterMap.get("Fan-Rtd")));
                int ledStatus = Integer.parseInt((afterMap.get("Led-Rtd")));
//            不知道设备上传的物联网卡号是不是写死的（就先手动修改）
//            String iotCardId = afterMap.get("SimId");
//            scdDeviceDao.setIotCardId(iotCardId);

                if (afterMap.containsKey("BeginTime-Rtd")) {
                    beginTime = afterMap.get("BeginTime-Rtd");
                    scdDeviceDao.setBeginTime(beginTime);
                }
//            log.info("\ndateTime:" + dateTime +"\nsunVoltRtd:" + sunVoltRtd + "\ncellVoltRtd:" + cellVoltRtd + "\ntempRtd:" + tempRtd + "\nlatitude:" + latitude_final
//            + "\nlongtitude:" + longitude_final + "\nfanStatus:" + fanStatus + "\nledStatus:" + ledStatus + "\nworkMode:" + workMode);


                //插入电量历史信息
                SCDDeviceBatteryInfo scdDeviceBatteryInfo = new SCDDeviceBatteryInfo().setDeviceId(deviceId).setBattery(battery).setInsertTime(date);
                scdDeviceMapper.insertBatteryInfo(scdDeviceBatteryInfo);

                SerDevicePermi devicePermiInfo = new SerDevicePermi();
                devicePermiInfo.setDeviceSerial(deviceId);
                devicePermiInfo.setBattery(battery);
                devicePermiInfo.setDeviceType("杀虫灯");
                devicePermiInfo.setTypeId(5);
//            devicePermiInfo.setLongitude(longitude_final);
//            devicePermiInfo.setLatitude(latitude_final);
                if (fanStatus == 1 || ledStatus == 1) {
                    devicePermiInfo.setOnlineState("在线");
                } else {
                    devicePermiInfo.setOnlineState("休眠");
                }

                scdDeviceDao.setCellVolt(cellVoltRtd);
                scdDeviceDao.setSunVolt(sunVoltRtd);
                scdDeviceDao.setDeviceId(deviceId);
                scdDeviceDao.setDeviceType(deviceType);
                scdDeviceDao.setTemp(tempRtd);
                scdDeviceDao.setUpdateTime(date);
                scdDeviceDao.setChannelName(channelName);
                scdDeviceDao.setBattery(battery);
                if (fanStatus == 1 || ledStatus == 1) {
                    scdDeviceDao.setDeviceStatus("在线");
                } else {
                    scdDeviceDao.setDeviceStatus("休眠");
                }

                if (workMode.startsWith("0")) {
                    scdDeviceDao.setWorkMode(0);
                } else {
                    scdDeviceDao.setWorkMode(1);
                }
//                long systemTime = System.currentTimeMillis();
//            log.info("updateTime:" + String.valueOf(date.getTime()) + "\nNow:" + systemTime);
//            if(systemTime - date.getTime() >= 86400000){
//                scdDeviceDao.setDeviceStatus(0);
//            }else{
//                scdDeviceDao.setDeviceStatus(1);
//            }
                scdDeviceDao.setFanStatus(fanStatus);
                scdDeviceDao.setLedStatus(ledStatus);
                if (scdDeviceMapper.selectSCDDeviceInfo(deviceId) != null) {
                    SCDDeviceDao scdDeviceInfo = scdDeviceMapper.selectSCDDeviceInfo(deviceId);
                    String nickName = scdDeviceInfo.getNickName();
                    devicePermiInfo.setDeviceName(nickName);
                    if (scdDeviceInfo.getLatitude() != formattedLatitude || scdDeviceInfo.getLongitude() != formattedLongitude) {
                        scdDeviceDao.setLatitude(formattedLatitude);
                        scdDeviceDao.setLongitude(formattedLongitude);
//                    devicePermiInfo.setLatitude(formattedLatitude);
//                    devicePermiInfo.setLongitude(formattedLongitude);
//                    JSONObject locationObject = LocationUtil.reverseGeoCode(longitude_final,latitude_final);
                        //详细地址，用于更新各个表中的地址
//                    String location = locationObject.getString("formattedAddress");
                        //具体城市，用于更新权限表种的area
//                    String area = locationObject.getString("city");
//                    scdDeviceDao.setLocation(location);
//                        Date updateTime = scdDeviceInfo.getUpdateTime();

//                    allDeviceInfo.setArea(area);
//                    devicePermiInfo.setArea(area);
                        //没效果
//                if(System.currentTimeMillis() - updateTime.getTime() > 86400000){
//                    allDeviceInfo.setOnlineState("离线");
//                    devicePermiInfo.setDeviceSerial("离线");
//                    scdDeviceDao.setDeviceStatus(0);
//                }else {
//                    allDeviceInfo.setOnlineState("在线");
//                    devicePermiInfo.setOnlineState("在线");
//                    scdDeviceInfo.setDeviceStatus(1);
//                }
                        Integer deviceNo = scdDeviceInfo.getId();
                        work_mode = scdDeviceInfo.getWorkMode();
                        beginTime = scdDeviceInfo.getBeginTime();
                        devicePermiInfo.setDeviceNo(deviceNo);
                        scdDeviceMapper.updateSCDDeviceInfo(scdDeviceDao);
                        if (devicePermiMapper.selectByDeviceSerial(deviceId) != null) {
                            devicePermiMapper.updateByPrimaryKeySelective(devicePermiInfo);
                        } else {
                            devicePermiMapper.insert(devicePermiInfo);
                        }
                    } else {
//                        Date updateTime = scdDeviceInfo.getUpdateTime();
                        Integer deviceNo = scdDeviceInfo.getId();
                        devicePermiInfo.setDeviceNo(deviceNo);
                        work_mode = scdDeviceInfo.getWorkMode();
                        beginTime = scdDeviceInfo.getBeginTime();
                        scdDeviceMapper.updateSCDDeviceInfo(scdDeviceDao);
                        if (devicePermiMapper.selectByDeviceSerial(deviceId) != null) {
                            devicePermiMapper.updateByPrimaryKeySelective(devicePermiInfo);
                        } else {
                            devicePermiMapper.insert(devicePermiInfo);
                        }
                    }
                } else {
                    if (fanStatus == 1 || ledStatus == 1) {

//                    JSONObject locationObject = LocationUtil.reverseGeoCode(longitude_final,latitude_final);
                        //详细地址，用于更新各个表中的地址
//                    String location = locationObject.getString("formattedAddress");
                        //具体城市，用于更新权限表种的area
//                    String area = locationObject.getString("city");
                        //更新杀虫灯设备表
                        scdDeviceDao.setLongitude(formattedLongitude);
                        scdDeviceDao.setLatitude(formattedLatitude);
                        scdDeviceDao.setDeviceStatus("在线");
//                    scdDeviceDao.setLocation(location);
                        //更新所有设备表（已不用）

//                    allDeviceInfo.setArea(area);
                        //更新权限设备表
//                    devicePermiInfo.setLongitude(formattedLongitude);
//                    devicePermiInfo.setLatitude(formattedLatitude);
                        devicePermiInfo.setOnlineState("在线");
//                    devicePermiInfo.setArea(area);
                    } else {
//                    JSONObject locationObject = LocationUtil.reverseGeoCode(longitude_final,latitude_final);
                        //详细地址，用于更新各个表中的地址
//                    String location = locationObject.getString("formattedAddress");
                        //具体城市，用于更新权限表种的area
//                    String area = locationObject.getString("city");
                        //更新杀虫灯设备表
                        scdDeviceDao.setLongitude(formattedLongitude);
                        scdDeviceDao.setLatitude(formattedLatitude);
                        scdDeviceDao.setDeviceStatus("休眠");
//                    scdDeviceDao.setLocation(location);
                        //更新所有设备表（已不用）
//                    allDeviceInfo.setArea(area);
                        //更新权限设备表
//                    devicePermiInfo.setLongitude(formattedLongitude);
//                    devicePermiInfo.setLatitude(formattedLatitude);
                        devicePermiInfo.setOnlineState("休眠");
//                    devicePermiInfo.setArea(area);
                    }
                    scdDeviceMapper.insertSCDDevice(scdDeviceDao);
                    devicePermiMapper.insert(devicePermiInfo);
                }
            }else if(deviceType.equals("1001")){
                iotFlag = 1;
                String simID = afterMap.get("SimID");
                //            用于更新气象土壤设备表
                if(iotDeviceMapper.selectIotDeviceByDeviceId(deviceId)!=null){
                    IotDeviceInfo selectIotDevice = iotDeviceMapper.selectIotDeviceByDeviceId(deviceId);
                    selectIotDevice.setDeviceStatus("在线").setBattery(battery).setLatitude(formattedLatitude).setLongitude(formattedLongitude);
                    iotDeviceMapper.updateDevice(selectIotDevice);
                    SerDevicePermi selectDevicePermi = devicePermiMapper.selectByDeviceSerial(deviceId);
                    selectDevicePermi.setOnlineState("在线").setBattery(battery).setLongitude(formattedLongitude).setLatitude(formattedLatitude);
                    devicePermiMapper.updateByPrimaryKeySelective(selectDevicePermi);
                }else{
                    IotDeviceInfo newDevice = new IotDeviceInfo().setDeviceId(deviceId).setDeviceName(deviceId).setSerial(deviceId).setDeviceType("weather")
                            .setLongitude(formattedLongitude).setLatitude(formattedLatitude).setBattery(battery).setSimId(simID);
                    iotDeviceMapper.insertIotDevice(newDevice);
                    SerDevicePermi newDevicePermi = new SerDevicePermi();
                    newDevicePermi.setDeviceSerial(deviceId).setDeviceName(deviceId).setDeviceType("气象站").setLongitude(formattedLongitude).setLatitude(formattedLatitude)
                            .setOnlineState("在线").setBattery(battery);
                    devicePermiMapper.insert(newDevicePermi);
                }
                Location location = new Location().setLatitude(formattedLatitude).setLongitude(formattedLongitude);
                //            光照数据
                Float airTemp = Float.valueOf(afterMap.get("AirTemp-Rtd"));
                Float airHum = Float.valueOf(afterMap.get("AirHum-Rtd"));
                Float rainFall = Float.valueOf(afterMap.get("RainFall-Rtd"));
                Float windDir = Float.valueOf(afterMap.get("WindDir-Rtd"));
                Float windSpeed = Float.valueOf(afterMap.get("WindSpd-Rtd"));
                Float lightInt = Float.valueOf(afterMap.get("LightInt-Rtd"));
                Weather weatherData = new Weather().setTemperature(airTemp).setHumidity(airHum).setRainfall(rainFall).setWind_direction(windDir).setWind_speed(windSpeed).setIllumination(lightInt).setBattery(battery.intValue());
                WeatherSenorDataPoints weatherSenorDataPoints = new WeatherSenorDataPoints().setDeviceId(deviceId).setType(1).setCreatedAt(Math.toIntExact(date.getTime()/1000))
                        .setLocation(location).setData(weatherData);
                iotDeviceMapper.insertWeatherDataPoints(weatherSenorDataPoints);
                log.info("天气数据添加成功");
            }



//            if(deviceInfoMapper.selectDeviceByDeviceSerial(deviceId) !=null){
//                Integer device_id = scdDeviceMapper.selectSCDDeviceInfo(deviceId).getId();
//                String nickName = scdDeviceMapper.selectSCDDeviceInfo(deviceId).getNickName();
//                allDeviceInfo.setDeviceId(device_id);
//                allDeviceInfo.setName(nickName);
//                deviceInfoMapper.updateDevice(allDeviceInfo);
//            }else{
//                deviceInfoMapper.insertDevice(allDeviceInfo);
//            }
            Integer finalWork_mode = work_mode;
            String finalBeginTime = beginTime;
            int finalIotFlag = iotFlag;
            ctx.channel().eventLoop().execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        SCDDeviceDao scdDeviceDao1 = scdDeviceMapper.selectSCDDeviceInfo(deviceId);
                        int flag = scdDeviceDao1.getIsRollback();
//                        log.info("flag = " + flag +"\nscdDeviceDao1:" + scdDeviceDao1);
//                        没有需要回调的设置或者是气象站设备
                        if(flag == 0 || finalIotFlag == 1) {
                            Thread.sleep(1000);
//                        long timeStamp = System.currentTimeMillis();
//                        String workMode;
                            String resStr = String.format("##0109QN=%s;ST=23;CN=2011;PW=123456;Reg=000571;Corp=001001;DevCls=0001;DevId=%s;Flag=5;CP=&&&&", QN_date, deviceId);
                            String temp = resStr.substring(6, 115);
                            byte[] result = temp.getBytes(StandardCharsets.UTF_8);
                            int crc = CRC16_HT212(result, 109);
                            String hex = Integer.toHexString(crc).toUpperCase();
                            String result_final = resStr + hex +"\r\n";
//                            log.info("返回的resStr为：" + result_final);
                            ctx.writeAndFlush(Unpooled.copiedBuffer(result_final, CharsetUtil.UTF_8));
                        }else{
                            if(finalWork_mode == 0) {
                                Thread.sleep(1000);
                                String modeHour = scdDeviceDao1.getModeHours();
//                                Integer workMode = scdDeviceDao1.getWorkMode();
//                                Integer workMode = 0;
                                scdDeviceDao1.setIsRollback(0);
                                scdDeviceDao1.setWorkMode(finalWork_mode);
                                String Mode = finalWork_mode + modeHour;
                                String resStr = String.format("##0118QN=%s;ST=23;CN=2011;PW=123456;Reg=000571;Corp=001001;DevCls=0001;DevId=%s;Flag=5;CP=&&Mode=%s&&", QN_date, deviceId, Mode);
                                String temp = resStr.substring(6, 124);
                                byte[] result = temp.getBytes(StandardCharsets.UTF_8);
                                int crc = CRC16_HT212(result, 118);
                                String hex = Integer.toHexString(crc).toUpperCase();
                                String result_final = resStr + hex + "\r\n";
//                                log.info("resFinal：" + result_final);
                                ctx.writeAndFlush(Unpooled.copiedBuffer(result_final, CharsetUtil.UTF_8));
                                scdDeviceMapper.updateSCDDeviceInfo(scdDeviceDao1);
                            }else{
                                Thread.sleep(1000);
                                String modeHour = scdDeviceDao1.getModeHours();
//                                Integer workMode = scdDeviceDao1.getWorkMode();
//                                Integer workMode = 0;
                                scdDeviceDao1.setIsRollback(0);
                                scdDeviceDao1.setBeginTime(finalBeginTime);
                                scdDeviceDao1.setWorkMode(finalWork_mode);
                                String Mode = finalWork_mode + modeHour;
                                String resStr = String.format("##0135QN=%s;ST=23;CN=2011;PW=123456;Reg=000571;Corp=001001;DevCls=0001;DevId=%s;Flag=5;CP=&&Mode=%s,BeginTime=%s&&", QN_date, deviceId, Mode, finalBeginTime);
                                String temp = resStr.substring(6, 141);
                                byte[] result = temp.getBytes(StandardCharsets.UTF_8);
                                int crc = CRC16_HT212(result, 135);
                                String hex = Integer.toHexString(crc).toUpperCase();
                                String result_final = resStr + hex + "\r\n";
                                log.info("resFinal：" + result_final);
                                ctx.writeAndFlush(Unpooled.copiedBuffer(result_final, CharsetUtil.UTF_8));
                                scdDeviceMapper.updateSCDDeviceInfo(scdDeviceDao1);
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            exceptionCaught(ctx,e);
        }
    }



    /**
     * 发生异常触发
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //当出现异常就关闭连接
        cause.printStackTrace();
        ctx.close();
    }

    public static int CRC16_HT212(byte[] msg, int dataLen) {
        int crcReg = 0xFFFF;
        for (int i = 0; i < dataLen; i++) {
            crcReg = (crcReg >> 8) ^ (msg[i] & 0xFF);
            for (int j = 0; j < 8; j++) {
                int check = crcReg & 0x0001;
                crcReg >>= 1;
                if (check == 0x0001) {
                    crcReg ^= 0xA001;
                }
            }
        }
        return crcReg;
    }
}


